agora inbox for pgsql-hackers@postgresql.orghelp / color / mirror / Atom feed
[PATCH 3/4] Reindent and wrap between added sect1 tags 653+ messages / 5 participants [nested] [flat]
* [PATCH 3/4] Reindent and wrap between added sect1 tags @ 2022-02-22 02:21 Chapman Flack <chap@anastigmatix.net> 0 siblings, 0 replies; 653+ messages in thread From: Chapman Flack @ 2022-02-22 02:21 UTC (permalink / raw) A whitespace-only commit. --- doc/src/sgml/plhandler.sgml | 638 ++++++++++++++++++++++---------------------- 1 file changed, 321 insertions(+), 317 deletions(-) diff --git a/doc/src/sgml/plhandler.sgml b/doc/src/sgml/plhandler.sgml index 95e8515..003a6c9 100644 --- a/doc/src/sgml/plhandler.sgml +++ b/doc/src/sgml/plhandler.sgml @@ -57,385 +57,389 @@ <sect1 id="plhandler-call"> <title>Call handler function</title> - <para> - Every routine defined with a language name other than - <literal>internal</literal> (as defined in <xref linkend="xfunc-internal"/>) - or <literal>c</literal> (<xref linkend="xfunc-c"/>) will be called by - invoking the procedural language's call handler. - <footnote> - <para> - This is true even of routines with language name <literal>sql</literal>, - though, as a special case, that call handler has no entry in the system - catalogs. - </para> - </footnote> - It is the responsibility of - the call handler to execute the routine in a meaningful way, such - as by interpreting the supplied source text. - </para> - - <para> - The call handler is a <quote>normal</quote> user-defined function that must - be declared to <productname>PostgreSQL</productname> as taking no arguments - and returning the type <type>language_handler</type>. This - special pseudo-type identifies the function as a call handler and - prevents it from being called directly in SQL commands. - This handler must not require a call handler of its own, which makes - the predefined languages <literal>internal</literal> or <literal>c</literal> - the only choices for the handler's own declaration. - Typically, it will be a loadable function in language - <literal>c</literal>, as described in <xref linkend="xfunc-c"/>. - <footnote> - <para> - It may be implemented in a language other than C, as long as it can be - built into a loadable object with compatible calling conventions. - </para> - </footnote> - </para> - - <para> - The call handler is called in the same way as any other function: - It receives a pointer to a - <structname>FunctionCallInfoBaseData</structname> <type>struct</type> containing - argument values and information about the called routine, and it - is expected to return a <type>Datum</type> result (and possibly - set the <structfield>isnull</structfield> field of the - <structname>FunctionCallInfoBaseData</structname> structure, if it wishes - to return an SQL null result). The difference between a call - handler and an ordinary callee is that the - <structfield>flinfo->fn_oid</structfield> field of the - <structname>FunctionCallInfoBaseData</structname> structure will contain - the OID of the actual routine to be called, not of the call - handler itself. The call handler must use this field to determine - which routine to execute. Also, the passed argument list has - been set up according to the declaration of the target routine, - not of the call handler. - </para> - - <para> - It's up to the call handler to fetch the routine's defining - <classname>pg_proc</classname> row from the system catalog cache - to determine what to execute, what parameter and return types are expected, - and so on. - The <literal>AS</literal> clause from the - <command>CREATE FUNCTION</command> or <command>CREATE PROCEDURE</command> - command for the routine will be found - in the <literal>prosrc</literal> column of the - <classname>pg_proc</classname> row. This is commonly source - text in the procedural language, but in theory it could be something else, - such as a path name to a file, or anything else that tells the call handler - what to do in detail. - </para> - - <para> - The handler may also examine the passed - <structname>FunctionCallInfoBaseData</structname> structure for information - on the context of the call. If the procedural language will support - returning sets, the structure may contain a pointer to a - <structname>ReturnSetInfo</structname> structure for use as described in - <xref linkend="xfunc-c-return-set"/>. If the language will support triggers - or event triggers, the structure may hold a pointer to one of the structures - described in <xref linkend="trigger-interface"/> or - <xref linkend="event-trigger-interface"/>, and the procedural language - should provide some way for the called function to use the information - they carry. - </para> - - <sect2 id="plhandler-call-args"> - <title>Parameter and return type resolution</title> - <para> - A routine's statically-declared parameter types (and, for a function, - return type) are found in the <literal>proargtypes</literal> and - <literal>prorettype</literal> columns of the <classname>pg_proc</classname> - row. - If a routine has <literal>OUT</literal> parameters, those types are - included in the <literal>proallargtypes</literal> column, and their names - in <literal>proargnames</literal>. - Convenience functions declared in <filename>funcapi.h</filename> are - available for extracting that information. + Every routine defined with a language name other than + <literal>internal</literal> (as defined in + <xref linkend="xfunc-internal"/>) + or <literal>c</literal> (<xref linkend="xfunc-c"/>) will be called by + invoking the procedural language's call handler. + <footnote> + <para> + This is true even of routines with language name <literal>sql</literal>, + though, as a special case, that call handler has no entry in the system + catalogs. + </para> + </footnote> + It is the responsibility of + the call handler to execute the routine in a meaningful way, such + as by interpreting the supplied source text. </para> <para> - The statically-declared types may include polymorphic types that need - to be resolved according to the actual types present at the call site, - as described in <xref linkend="xfunc-c-polymorphism"/>. + The call handler is a <quote>normal</quote> user-defined function that must + be declared to <productname>PostgreSQL</productname> as taking no arguments + and returning the type <type>language_handler</type>. This + special pseudo-type identifies the function as a call handler and + prevents it from being called directly in SQL commands. + This handler must not require a call handler of its own, which makes + the predefined languages <literal>internal</literal> or + <literal>c</literal> the only choices for the handler's own declaration. + Typically, it will be a loadable function in language + <literal>c</literal>, as described in <xref linkend="xfunc-c"/>. + <footnote> + <para> + It may be implemented in a language other than C, as long as it can be + built into a loadable object with compatible calling conventions. + </para> + </footnote> </para> - </sect2> - - <sect2 id="plhandler-call-types"> - <title>Mapping to procedural language types</title> + <para> + The call handler is called in the same way as any other function: + It receives a pointer to a + <structname>FunctionCallInfoBaseData</structname> <type>struct</type> + containing argument values and information about the called routine, and it + is expected to return a <type>Datum</type> result (and possibly + set the <structfield>isnull</structfield> field of the + <structname>FunctionCallInfoBaseData</structname> structure, if it wishes + to return an SQL null result). The difference between a call + handler and an ordinary callee is that the + <structfield>flinfo->fn_oid</structfield> field of the + <structname>FunctionCallInfoBaseData</structname> structure will contain + the OID of the actual routine to be called, not of the call + handler itself. The call handler must use this field to determine + which routine to execute. Also, the passed argument list has + been set up according to the declaration of the target routine, + not of the call handler. + </para> <para> - Once the <productname>PostgreSQL</productname> types of any parameters - and results have been resolved, the handler must determine how it will - map their values to and from suitable types that exist in the procedural - language. + It's up to the call handler to fetch the routine's defining + <classname>pg_proc</classname> row from the system catalog cache + to determine what to execute, what parameter and return types are expected, + and so on. + The <literal>AS</literal> clause from the + <command>CREATE FUNCTION</command> or <command>CREATE PROCEDURE</command> + command for the routine will be found + in the <literal>prosrc</literal> column of the + <classname>pg_proc</classname> row. This is commonly source + text in the procedural language, but in theory it could be something else, + such as a path name to a file, or anything else that tells the call handler + what to do in detail. </para> <para> - The designer of a procedural language will typically document what types - will be supported and how they will be mapped, which could be as simple - as using every type's text input/output format to map it to the target - language's string type, or could directly map many types to corresponding - ones the target language provides. The handler function will implement - those rules. + The handler may also examine the passed + <structname>FunctionCallInfoBaseData</structname> structure for information + on the context of the call. If the procedural language will support + returning sets, the structure may contain a pointer to a + <structname>ReturnSetInfo</structname> structure for use as described in + <xref linkend="xfunc-c-return-set"/>. If the language will support triggers + or event triggers, the structure may hold a pointer to one of + the structures described in <xref linkend="trigger-interface"/> or + <xref linkend="event-trigger-interface"/>, and the procedural language + should provide some way for the called function to use the information + they carry. </para> - <sect3 id="plhandler-call-types-transform"> - <title>Type transforms</title> + <sect2 id="plhandler-call-args"> + <title>Parameter and return type resolution</title> <para> - Because <productname>PostgreSQL</productname> is extensible, and - an extension can easily supply new types, a procedural language handler - may encounter types it has no predefined mappings for, or only an awkward - default mapping such as to a text string. A procedural language can be - designed so that its type mappings are also extensible, and an extension - can add mappings between new <productname>PostgreSQL</productname> types - and suitable types in the target language. + A routine's statically-declared parameter types (and, for a function, + return type) are found in the <literal>proargtypes</literal> and + <literal>prorettype</literal> columns of the + <classname>pg_proc</classname> row. + If a routine has <literal>OUT</literal> parameters, those types are + included in the <literal>proallargtypes</literal> column, and their names + in <literal>proargnames</literal>. + Convenience functions declared in <filename>funcapi.h</filename> are + available for extracting that information. </para> <para> - One mechanism <productname>PostgreSQL</productname> provides that may be - used for that purpose is <xref linkend="sql-createtransform"/>. - The command associates a <productname>PostgreSQL</productname> type and - a specific procedural language with a pair of functions to handle the - mapping of that type to a corresponding procedural language type and back. + The statically-declared types may include polymorphic types that need + to be resolved according to the actual types present at the call site, + as described in <xref linkend="xfunc-c-polymorphism"/>. </para> - <para> - For a procedural language to support transforms, its call handler is - responsible for consulting the <literal>protrftypes</literal> column of - a routine's <classname>pg_proc</classname> row to determine which types - should have transforms applied. - A convenience function <function>get_call_trftypes</function> is - available. - The call handler must then resolve the <quote>from SQL</quote> function - for each affected parameter type, and the <quote>to SQL</quote> function - for any affected result. - It may use the <function>get_transform_fromsql</function> and - <function>get_transform_tosql</function> functions for that. - </para> + </sect2> - <para> - The handler must then apply the proper <quote>from SQL</quote> functions - to all affected inputs (including elements within array or composite - types) and, after calling the target routine, apply the proper - <quote>to SQL</quote> functions similarly to any results. - If the target routine might interact with the database using SPI, - the handler may arrange for the requested transforms to be applied - in those operations as well. - </para> + <sect2 id="plhandler-call-types"> + <title>Mapping to procedural language types</title> <para> - Because the procedural language implementation, and not - <productname>PostgreSQL</productname> itself, is responsible for calling - the transform functions, it is free to define what it will pass as the - parameter to each function (declared as <type>internal</type> for both), - and how it will interpret the result (also declared <type>internal</type>) - of the <quote>from SQL</quote> function. Effectively, each procedural - language's implementation defines the API that must be adhered to - by any author of transforms for that language. + Once the <productname>PostgreSQL</productname> types of any parameters + and results have been resolved, the handler must determine how it will + map their values to and from suitable types that exist in the procedural + language. </para> <para> - A procedural language might impose limits on where and how it will apply - transforms (such as on array or domain types). The - <function>get_transform_fromsql</function> and - <function>get_transform_tosql</function> functions mentioned above - consider each type only shallowly, and will not, for example, return - a transform function for a domain type if only its base type was listed in - the <literal>TRANSFORM</literal> clause. - If a procedural language's call handler does not implement transforms - at all, no <literal>TRANSFORM</literal> clause will have any effect - for routines declared in that language. - The language's validator function can be used to give immediate feedback - if a routine is declared with <literal>TRANSFORM</literal> clauses - the implementation cannot support. + The designer of a procedural language will typically document what types + will be supported and how they will be mapped, which could be as simple + as using every type's text input/output format to map it to the target + language's string type, or could directly map many types to corresponding + ones the target language provides. The handler function will implement + those rules. </para> - </sect3> - - </sect2> - - <sect2 id="plhandler-call-cache"> - <title>Caching resolved routine information</title> + <sect3 id="plhandler-call-types-transform"> + <title>Type transforms</title> + + <para> + Because <productname>PostgreSQL</productname> is extensible, and + an extension can easily supply new types, a procedural language handler + may encounter types it has no predefined mappings for, or only an awkward + default mapping such as to a text string. A procedural language can be + designed so that its type mappings are also extensible, and an extension + can add mappings between new <productname>PostgreSQL</productname> types + and suitable types in the target language. + </para> + + <para> + One mechanism <productname>PostgreSQL</productname> provides that may be + used for that purpose is <xref linkend="sql-createtransform"/>. + The command associates a <productname>PostgreSQL</productname> type and + a specific procedural language with a pair of functions to handle the + mapping of that type to a corresponding procedural language type + and back. + </para> + + <para> + For a procedural language to support transforms, its call handler is + responsible for consulting the <literal>protrftypes</literal> column of + a routine's <classname>pg_proc</classname> row to determine which types + should have transforms applied. + A convenience function <function>get_call_trftypes</function> is + available. + The call handler must then resolve the <quote>from SQL</quote> function + for each affected parameter type, and the <quote>to SQL</quote> function + for any affected result. + It may use the <function>get_transform_fromsql</function> and + <function>get_transform_tosql</function> functions for that. + </para> + + <para> + The handler must then apply the proper <quote>from SQL</quote> functions + to all affected inputs (including elements within array or composite + types) and, after calling the target routine, apply the proper + <quote>to SQL</quote> functions similarly to any results. + If the target routine might interact with the database using SPI, + the handler may arrange for the requested transforms to be applied + in those operations as well. + </para> + + <para> + Because the procedural language implementation, and not + <productname>PostgreSQL</productname> itself, is responsible for calling + the transform functions, it is free to define what it will pass as the + parameter to each function (declared as <type>internal</type> for both), + and how it will interpret the result (also declared + <type>internal</type>) of the <quote>from SQL</quote> function. + Effectively, each procedural language's implementation defines the API + that must be adhered to by any author of transforms for that language. + </para> + + <para> + A procedural language might impose limits on where and how it will apply + transforms (such as on array or domain types). The + <function>get_transform_fromsql</function> and + <function>get_transform_tosql</function> functions mentioned above + consider each type only shallowly, and will not, for example, return + a transform function for a domain type if only its base type was listed + in the <literal>TRANSFORM</literal> clause. + If a procedural language's call handler does not implement transforms + at all, no <literal>TRANSFORM</literal> clause will have any effect + for routines declared in that language. + The language's validator function can be used to give immediate feedback + if a routine is declared with <literal>TRANSFORM</literal> clauses + the implementation cannot support. + </para> + + </sect3> + + </sect2> + + <sect2 id="plhandler-call-cache"> + <title>Caching resolved routine information</title> - <para> - Often, the same routine is called many times per SQL statement. - A call handler can avoid repeated lookups of information about the - called routine by using the - <structfield>flinfo->fn_extra</structfield> field. This will - initially be <symbol>NULL</symbol>, but can be set by the call handler to point at - information about the called routine. On subsequent calls, if - <structfield>flinfo->fn_extra</structfield> is already non-<symbol>NULL</symbol> - then it can be used and the information lookup step skipped. The - call handler must make sure that - <structfield>flinfo->fn_extra</structfield> is made to point at - memory that will live at least until the end of the current query, - since an <structname>FmgrInfo</structname> data structure could be - kept that long. One way to do this is to allocate the extra data - in the memory context specified by - <structfield>flinfo->fn_mcxt</structfield>; such data will - normally have the same lifespan as the - <structname>FmgrInfo</structname> itself. But the handler could - also choose to use a longer-lived memory context so that it can cache - routine definition information across queries. - </para> + <para> + Often, the same routine is called many times per SQL statement. + A call handler can avoid repeated lookups of information about the + called routine by using the + <structfield>flinfo->fn_extra</structfield> field. This will + initially be <symbol>NULL</symbol>, but can be set by the call handler + to point at information about the called routine. On subsequent calls, + if <structfield>flinfo->fn_extra</structfield> is already + non-<symbol>NULL</symbol> then it can be used and the information lookup + step skipped. The call handler must make sure that + <structfield>flinfo->fn_extra</structfield> is made to point at + memory that will live at least until the end of the current query, + since an <structname>FmgrInfo</structname> data structure could be + kept that long. One way to do this is to allocate the extra data + in the memory context specified by + <structfield>flinfo->fn_mcxt</structfield>; such data will + normally have the same lifespan as the + <structname>FmgrInfo</structname> itself. But the handler could + also choose to use a longer-lived memory context so that it can cache + routine definition information across queries. + </para> - <para> - If the handler supports returning sets, and uses the ValuePerCall mode - helper macros described in <xref linkend="xfunc-c-return-set"/>, it must - not use <structfield>fn_extra</structfield> during set-returning calls. - The helper macros use that field for their own purposes. After - <literal>SRF_FIRSTCALL_INIT</literal> has been called, the field will point - to a <structname>FuncCallContext</structname> structure, which has - a <structfield>user_fctx</structfield> field that can be used similarly, - but only through the sequence of calls returning one set result. - </para> + <para> + If the handler supports returning sets, and uses the ValuePerCall mode + helper macros described in <xref linkend="xfunc-c-return-set"/>, it must + not use <structfield>fn_extra</structfield> during set-returning calls. + The helper macros use that field for their own purposes. After + <literal>SRF_FIRSTCALL_INIT</literal> has been called, the field will point + to a <structname>FuncCallContext</structname> structure, which has + a <structfield>user_fctx</structfield> field that can be used similarly, + but only through the sequence of calls returning one set result. + </para> - </sect2> + </sect2> </sect1> <sect1 id="plhandler-validator"> <title>Validator function</title> - <para> - If a validator is provided by a procedural language, it - must be declared as a function taking a single parameter of type - <type>oid</type>. The validator's result is ignored, so it is customarily - declared to return <type>void</type>. - The validator itself may be written in any procedural language able to - receive an <type>oid</type>-typed parameter and query system catalogs. - </para> + <para> + If a validator is provided by a procedural language, it + must be declared as a function taking a single parameter of type + <type>oid</type>. The validator's result is ignored, so it is customarily + declared to return <type>void</type>. + The validator itself may be written in any procedural language able to + receive an <type>oid</type>-typed parameter and query system catalogs. + </para> - <para> - The validator will be called at - the end of a <command>CREATE FUNCTION</command> or - <command>CREATE PROCEDURE</command> command that has created - or updated a routine written in the procedural language. - The passed-in OID is the OID of the routine's <classname>pg_proc</classname> - row. The validator must fetch this row in the usual way, and do - whatever checking is appropriate. - </para> + <para> + The validator will be called at + the end of a <command>CREATE FUNCTION</command> or + <command>CREATE PROCEDURE</command> command that has created + or updated a routine written in the procedural language. + The passed-in OID is the OID of the routine's + <classname>pg_proc</classname> row. The validator must fetch this row + in the usual way, and do whatever checking is appropriate. + </para> - <para> - First, call <function>CheckFunctionValidatorAccess()</function> to diagnose - explicit calls to the validator that the user could not achieve through - <command>CREATE FUNCTION</command> or <command>CREATE PROCEDURE</command>. - Typical checks then include verifying - that the routine's argument and result types are supported by the - language, and that the routine's body is syntactically correct - in the language. If the validator finds the routine to be okay, - it should just return. If it finds an error, it should report that - via the normal <function>ereport()</function> error reporting mechanism. - Throwing an error will force a transaction rollback and thus prevent - the incorrect routine definition from being committed. - </para> + <para> + First, call <function>CheckFunctionValidatorAccess()</function> + to diagnose explicit calls to the validator that the user could not achieve + through <command>CREATE FUNCTION</command> or + <command>CREATE PROCEDURE</command>. + Typical checks then include verifying + that the routine's argument and result types are supported by the + language, and that the routine's body is syntactically correct + in the language. If the validator finds the routine to be okay, + it should just return. If it finds an error, it should report that + via the normal <function>ereport()</function> error reporting mechanism. + Throwing an error will force a transaction rollback and thus prevent + the incorrect routine definition from being committed. + </para> - <para> - Validator functions should typically honor the <xref - linkend="guc-check-function-bodies"/> parameter: if it is turned off then - any expensive or context-sensitive checking should be skipped. If the - language provides for code execution at compilation time, the validator - must suppress checks that would induce such execution. In particular, - this parameter is turned off by <application>pg_dump</application> so that it can - load procedural language routines without worrying about side effects or - dependencies of the routine bodies on other database objects. - (Because of this requirement, the call handler should avoid - assuming that the validator has fully checked the routine. The point - of having a validator is not to let the call handler omit checks, but - to notify the user immediately if there are obvious errors in a - <command>CREATE FUNCTION</command> or <command>CREATE PROCEDURE</command> - command.) - </para> + <para> + Validator functions should typically honor the <xref + linkend="guc-check-function-bodies"/> parameter: if it is turned off then + any expensive or context-sensitive checking should be skipped. If the + language provides for code execution at compilation time, the validator + must suppress checks that would induce such execution. In particular, + this parameter is turned off by <application>pg_dump</application> so that + it can load procedural language routines without worrying about + side effects or dependencies of the routine bodies on other database + objects. + (Because of this requirement, the call handler should avoid + assuming that the validator has fully checked the routine. The point + of having a validator is not to let the call handler omit checks, but + to notify the user immediately if there are obvious errors in a + <command>CREATE FUNCTION</command> or <command>CREATE PROCEDURE</command> + command.) + </para> - <para> - While the choice of exactly what to check is mostly left to the - discretion of the validator function, note that the core - <command>CREATE FUNCTION</command> and <command>CREATE PROCEDURE</command> - code only executes <literal>SET</literal> clauses - attached to a routine when <varname>check_function_bodies</varname> is on. - Therefore, checks whose results might be affected by GUC parameters - definitely should be skipped when <varname>check_function_bodies</varname> is - off, to avoid false failures when reloading a dump. - </para> + <para> + While the choice of exactly what to check is mostly left to the + discretion of the validator function, note that the core + <command>CREATE FUNCTION</command> and <command>CREATE PROCEDURE</command> + code only executes <literal>SET</literal> clauses + attached to a routine when <varname>check_function_bodies</varname> is on. + Therefore, checks whose results might be affected by GUC parameters + definitely should be skipped when <varname>check_function_bodies</varname> + is off, to avoid false failures when reloading a dump. + </para> - <para> - If a language's call handler does not apply parameter and return type - transforms, then no <literal>TRANSFORM</literal> clause in a routine - declaration will have any effect. To provide immediate feedback if a - declaration contains such a clause, the validator can report a suitable - error whenever the <literal>protrftypes</literal> column of the routine's - <classname>pg_proc</classname> row is non-null. - </para> + <para> + If a language's call handler does not apply parameter and return type + transforms, then no <literal>TRANSFORM</literal> clause in a routine + declaration will have any effect. To provide immediate feedback if a + declaration contains such a clause, the validator can report a suitable + error whenever the <literal>protrftypes</literal> column of the routine's + <classname>pg_proc</classname> row is non-null. + </para> </sect1> <sect1 id="plhandler-inline"> <title>Inline handler function</title> - <para> - If this handler is provided by a procedural language, it - must be declared as a function taking a single parameter of type - <type>internal</type>, which will be a pointer - to an <structname>InlineCodeBlock</structname> struct when the handler - is called. The result is ignored, so the return type is customarily - declared as <type>void</type>. - The inline handler itself may be written in any procedural language that - permits declaring an <type>internal</type> parameter with a suitable - language binding for accessing it as an - <structname>InlineCodeBlock</structname> struct. - </para> + <para> + If this handler is provided by a procedural language, it + must be declared as a function taking a single parameter of type + <type>internal</type>, which will be a pointer + to an <structname>InlineCodeBlock</structname> struct when the handler + is called. The result is ignored, so the return type is customarily + declared as <type>void</type>. + The inline handler itself may be written in any procedural language that + permits declaring an <type>internal</type> parameter with a suitable + language binding for accessing it as an + <structname>InlineCodeBlock</structname> struct. + </para> - <para> - The inline handler - will be called when a <command>DO</command> statement is executed specifying - the procedural language. The <structname>InlineCodeBlock</structname> - struct contains information - about the <command>DO</command> statement's parameters, in particular the - text of the anonymous code block to be executed. - It also contains the OID of the intended procedural language and whether - that procedural language is declared as <literal>TRUSTED</literal>, useful - if a single inline handler is supporting more than one procedural language. - The inline handler should execute the code block and return. - </para> + <para> + The inline handler + will be called when a <command>DO</command> statement is executed + specifying the procedural language. + The <structname>InlineCodeBlock</structname> struct contains information + about the <command>DO</command> statement's parameters, in particular the + text of the anonymous code block to be executed. + It also contains the OID of the intended procedural language and whether + that procedural language is declared as <literal>TRUSTED</literal>, useful + if a single inline handler is supporting more than one procedural language. + The inline handler should execute the code block and return. + </para> </sect1> <sect1 id="plhandler-packaging"> <title>Packaging the language handlers</title> - <para> - It's recommended that you wrap all these function declarations, - as well as the <command>CREATE LANGUAGE</command> command itself, into - an <firstterm>extension</firstterm> so that a simple <command>CREATE EXTENSION</command> - command is sufficient to install the language. See - <xref linkend="extend-extensions"/> for information about writing - extensions. - </para> + <para> + It's recommended that you wrap all these function declarations, + as well as the <command>CREATE LANGUAGE</command> command itself, into + an <firstterm>extension</firstterm> so that a simple + <command>CREATE EXTENSION</command> command is sufficient to install + the language. See <xref linkend="extend-extensions"/> for information + about writing extensions. + </para> </sect1> <sect1 id="plhandler-examples"> <title>Example code</title> - <para> - A template for a procedural-language handler written as a C extension is - provided in <literal>src/test/modules/plsample</literal>. This is a - working sample demonstrating one way to create a procedural-language - handler, process parameters, and return a value. - </para> + <para> + A template for a procedural-language handler written as a C extension is + provided in <literal>src/test/modules/plsample</literal>. This is a + working sample demonstrating one way to create a procedural-language + handler, process parameters, and return a value. + </para> - <para> - The procedural languages included in the standard distribution - are good references when trying to write your own language handler. - Look into the <filename>src/pl</filename> subdirectory of the source tree. - The <xref linkend="sql-createlanguage"/> - reference page also has some useful details. - </para> + <para> + The procedural languages included in the standard distribution + are good references when trying to write your own language handler. + Look into the <filename>src/pl</filename> subdirectory of the source tree. + The <xref linkend="sql-createlanguage"/> + reference page also has some useful details. + </para> </sect1> -- 2.7.3 --------------070002080407000808050907 Content-Type: text/x-patch; name="4.patch" Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename="4.patch" ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1] WIP: Evaluate arguments of correlated SubPlans in the referencing ExprState @ 2023-02-25 21:39 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 653+ messages in thread From: Andres Freund @ 2023-02-25 21:39 UTC (permalink / raw) --- src/include/nodes/execnodes.h | 1 - src/backend/executor/execExpr.c | 81 +++++++++++++++++------------ src/backend/executor/execProcnode.c | 5 ++ src/backend/executor/nodeSubplan.c | 30 +++++------ 4 files changed, 66 insertions(+), 51 deletions(-) diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h index 20f4c8b35f3..437cf8b5a02 100644 --- a/src/include/nodes/execnodes.h +++ b/src/include/nodes/execnodes.h @@ -947,7 +947,6 @@ typedef struct SubPlanState struct PlanState *planstate; /* subselect plan's state tree */ struct PlanState *parent; /* parent plan node's state tree */ ExprState *testexpr; /* state of combining expression */ - List *args; /* states of argument expression(s) */ HeapTuple curTuple; /* copy of most recent tuple from subplan */ Datum curArray; /* most recent array from ARRAY() subplan */ /* these are used when hashing the subselect's output: */ diff --git a/src/backend/executor/execExpr.c b/src/backend/executor/execExpr.c index c61f23c6c18..7a9d5729b4b 100644 --- a/src/backend/executor/execExpr.c +++ b/src/backend/executor/execExpr.c @@ -87,6 +87,9 @@ static void ExecBuildAggTransCall(ExprState *state, AggState *aggstate, FunctionCallInfo fcinfo, AggStatePerTrans pertrans, int transno, int setno, int setoff, bool ishash, bool nullcheck); +static void ExecInitSubPlanExpr(SubPlan *subplan, + ExprState *state, + Datum *resv, bool *resnull); /* @@ -1388,7 +1391,6 @@ ExecInitExprRec(Expr *node, ExprState *state, case T_SubPlan: { SubPlan *subplan = (SubPlan *) node; - SubPlanState *sstate; /* * Real execution of a MULTIEXPR SubPlan has already been @@ -1405,19 +1407,7 @@ ExecInitExprRec(Expr *node, ExprState *state, break; } - if (!state->parent) - elog(ERROR, "SubPlan found with no parent plan"); - - sstate = ExecInitSubPlan(subplan, state->parent); - - /* add SubPlanState nodes to state->parent->subPlan */ - state->parent->subPlan = lappend(state->parent->subPlan, - sstate); - - scratch.opcode = EEOP_SUBPLAN; - scratch.d.subplan.sstate = sstate; - - ExprEvalPushStep(state, &scratch); + ExecInitSubPlanExpr(subplan, state, resv, resnull); break; } @@ -2618,29 +2608,12 @@ ExecPushExprSetupSteps(ExprState *state, ExprSetupInfo *info) foreach(lc, info->multiexpr_subplans) { SubPlan *subplan = (SubPlan *) lfirst(lc); - SubPlanState *sstate; Assert(subplan->subLinkType == MULTIEXPR_SUBLINK); - /* This should match what ExecInitExprRec does for other SubPlans: */ - - if (!state->parent) - elog(ERROR, "SubPlan found with no parent plan"); - - sstate = ExecInitSubPlan(subplan, state->parent); - - /* add SubPlanState nodes to state->parent->subPlan */ - state->parent->subPlan = lappend(state->parent->subPlan, - sstate); - - scratch.opcode = EEOP_SUBPLAN; - scratch.d.subplan.sstate = sstate; - /* The result can be ignored, but we better put it somewhere */ - scratch.resvalue = &state->resvalue; - scratch.resnull = &state->resnull; - - ExprEvalPushStep(state, &scratch); + ExecInitSubPlanExpr(subplan, state, + &state->resvalue, &state->resnull); } } @@ -4040,3 +4013,45 @@ ExecBuildParamSetEqual(TupleDesc desc, return state; } + +static void +ExecInitSubPlanExpr(SubPlan *subplan, + ExprState *state, + Datum *resv, bool *resnull) +{ + ExprEvalStep scratch = {0}; + SubPlanState *sstate; + ListCell *pvar; + ListCell *l; + EState *estate = state->parent->state; + + if (!state->parent) + elog(ERROR, "SubPlan found with no parent plan"); + + /* + * Generate steps to evaluate input arguments for the subplan. + * + * Any calculation we have to do can be done in the parent econtext, since + * the Param values don't need to have per-query lifetime. + */ + forboth(l, subplan->parParam, pvar, subplan->args) + { + int paramid = lfirst_int(l); + ParamExecData *prm = &estate->es_param_exec_vals[paramid]; + + ExecInitExprRec(lfirst(pvar), state, &prm->value, &prm->isnull); + } + + sstate = ExecInitSubPlan(subplan, state->parent); + + /* add SubPlanState nodes to state->parent->subPlan */ + state->parent->subPlan = lappend(state->parent->subPlan, + sstate); + + scratch.opcode = EEOP_SUBPLAN; + scratch.resvalue = resv; + scratch.resnull = resnull; + scratch.d.subplan.sstate = sstate; + + ExprEvalPushStep(state, &scratch); +} diff --git a/src/backend/executor/execProcnode.c b/src/backend/executor/execProcnode.c index 4d288bc8d41..f62bb28140f 100644 --- a/src/backend/executor/execProcnode.c +++ b/src/backend/executor/execProcnode.c @@ -393,6 +393,10 @@ ExecInitNode(Plan *node, EState *estate, int eflags) /* * Initialize any initPlans present in this node. The planner put them in * a separate list for us. + * + * The defining characteristic of initplans is that they don't have + * arguments, so we don't need to evaluate them (in contrast to + * ExecInitSubPlanExpr()). */ subps = NIL; foreach(l, node->initPlan) @@ -401,6 +405,7 @@ ExecInitNode(Plan *node, EState *estate, int eflags) SubPlanState *sstate; Assert(IsA(subplan, SubPlan)); + Assert(subplan->args == NIL); sstate = ExecInitSubPlan(subplan, result); subps = lappend(subps, sstate); } diff --git a/src/backend/executor/nodeSubplan.c b/src/backend/executor/nodeSubplan.c index c136f75ac24..3458ac007cd 100644 --- a/src/backend/executor/nodeSubplan.c +++ b/src/backend/executor/nodeSubplan.c @@ -107,7 +107,7 @@ ExecHashSubPlan(SubPlanState *node, TupleTableSlot *slot; /* Shouldn't have any direct correlation Vars */ - if (subplan->parParam != NIL || node->args != NIL) + if (subplan->parParam != NIL || subplan->args != NIL) elog(ERROR, "hashed subplan with direct correlation not supported"); /* @@ -231,7 +231,6 @@ ExecScanSubPlan(SubPlanState *node, TupleTableSlot *slot; Datum result; bool found = false; /* true if got at least one subplan tuple */ - ListCell *pvar; ListCell *l; ArrayBuildStateAny *astate = NULL; @@ -248,26 +247,20 @@ ExecScanSubPlan(SubPlanState *node, oldcontext = MemoryContextSwitchTo(econtext->ecxt_per_query_memory); /* - * Set Params of this plan from parent plan correlation values. (Any - * calculation we have to do is done in the parent econtext, since the - * Param values don't need to have per-query lifetime.) + * We rely on the caller to evaluate plan correlation values, if + * necessary. However we still need to record the fact that the values + * (might have) changed, otherwise the ExecReScan() below won't know that + * nodes need to be rescanned. */ - Assert(list_length(subplan->parParam) == list_length(node->args)); - - forboth(l, subplan->parParam, pvar, node->args) + Assert(list_length(subplan->parParam) == list_length(subplan->args)); + foreach(l, subplan->parParam) { int paramid = lfirst_int(l); - ParamExecData *prm = &(econtext->ecxt_param_exec_vals[paramid]); - prm->value = ExecEvalExprSwitchContext((ExprState *) lfirst(pvar), - econtext, - &(prm->isnull)); planstate->chgParam = bms_add_member(planstate->chgParam, paramid); } - /* - * Now that we've set up its parameters, we can reset the subplan. - */ + /* with that done, we can reset the subplan */ ExecReScan(planstate); /* @@ -817,6 +810,10 @@ slotNoNulls(TupleTableSlot *slot) * as well as regular SubPlans. Note that we don't link the SubPlan into * the parent's subPlan list, because that shouldn't happen for InitPlans. * Instead, ExecInitExpr() does that one part. + * + * We also rely on ExecInitExpr(), more precisely ExecInitSubPlanExpr(), to + * evaluate input parameters, as that allows them to be evaluated as part of + * the expression referencing the SubPlan. * ---------------------------------------------------------------- */ SubPlanState * @@ -844,7 +841,6 @@ ExecInitSubPlan(SubPlan *subplan, PlanState *parent) /* Initialize subexpressions */ sstate->testexpr = ExecInitExpr((Expr *) subplan->testexpr, parent); - sstate->args = ExecInitExprList(subplan->args, parent); /* * initialize my state @@ -1107,7 +1103,7 @@ ExecSetParamPlan(SubPlanState *node, ExprContext *econtext) elog(ERROR, "ANY/ALL subselect unsupported as initplan"); if (subLinkType == CTE_SUBLINK) elog(ERROR, "CTE subplans should not be executed via ExecSetParamPlan"); - if (subplan->parParam || node->args) + if (subplan->parParam || subplan->args) elog(ERROR, "correlated subplans should not be executed via ExecSetParamPlan"); /* -- 2.38.0 --6ir4gcdcv6d4j3qy-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2] WIP: Evaluate arguments of correlated SubPlans in the referencing ExprState @ 2023-02-25 21:39 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 653+ messages in thread From: Andres Freund @ 2023-02-25 21:39 UTC (permalink / raw) --- src/include/executor/execExpr.h | 6 +- src/include/nodes/execnodes.h | 1 - src/backend/executor/execExpr.c | 93 +++++++++++++++++---------- src/backend/executor/execExprInterp.c | 22 +++++++ src/backend/executor/execProcnode.c | 5 ++ src/backend/executor/nodeSubplan.c | 30 ++++----- src/backend/jit/llvm/llvmjit_expr.c | 6 ++ src/backend/jit/llvm/llvmjit_types.c | 1 + 8 files changed, 112 insertions(+), 52 deletions(-) diff --git a/src/include/executor/execExpr.h b/src/include/executor/execExpr.h index 06c3adc0a19..ca2b7306cd0 100644 --- a/src/include/executor/execExpr.h +++ b/src/include/executor/execExpr.h @@ -158,6 +158,8 @@ typedef enum ExprEvalOp EEOP_PARAM_EXEC, EEOP_PARAM_EXTERN, EEOP_PARAM_CALLBACK, + /* set PARAM_EXEC value */ + EEOP_PARAM_SET, /* return CaseTestExpr value */ EEOP_CASE_TESTVAL, @@ -374,7 +376,7 @@ typedef struct ExprEvalStep ExprEvalRowtypeCache rowcache; } nulltest_row; - /* for EEOP_PARAM_EXEC/EXTERN */ + /* for EEOP_PARAM_EXEC/EXTERN and EEOP_PARAM_SET */ struct { int paramid; /* numeric ID for parameter */ @@ -738,6 +740,8 @@ extern void ExecEvalParamExec(ExprState *state, ExprEvalStep *op, ExprContext *econtext); extern void ExecEvalParamExtern(ExprState *state, ExprEvalStep *op, ExprContext *econtext); +extern void ExecEvalParamSet(ExprState *state, ExprEvalStep *op, + ExprContext *econtext); extern void ExecEvalCurrentOfExpr(ExprState *state, ExprEvalStep *op); extern void ExecEvalNextValueExpr(ExprState *state, ExprEvalStep *op); extern void ExecEvalRowNull(ExprState *state, ExprEvalStep *op, diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h index e7eb1e666ff..16e95e4cb48 100644 --- a/src/include/nodes/execnodes.h +++ b/src/include/nodes/execnodes.h @@ -947,7 +947,6 @@ typedef struct SubPlanState struct PlanState *planstate; /* subselect plan's state tree */ struct PlanState *parent; /* parent plan node's state tree */ ExprState *testexpr; /* state of combining expression */ - List *args; /* states of argument expression(s) */ HeapTuple curTuple; /* copy of most recent tuple from subplan */ Datum curArray; /* most recent array from ARRAY() subplan */ /* these are used when hashing the subselect's output: */ diff --git a/src/backend/executor/execExpr.c b/src/backend/executor/execExpr.c index c61f23c6c18..002f2a0091f 100644 --- a/src/backend/executor/execExpr.c +++ b/src/backend/executor/execExpr.c @@ -87,6 +87,9 @@ static void ExecBuildAggTransCall(ExprState *state, AggState *aggstate, FunctionCallInfo fcinfo, AggStatePerTrans pertrans, int transno, int setno, int setoff, bool ishash, bool nullcheck); +static void ExecInitSubPlanExpr(SubPlan *subplan, + ExprState *state, + Datum *resv, bool *resnull); /* @@ -1388,7 +1391,6 @@ ExecInitExprRec(Expr *node, ExprState *state, case T_SubPlan: { SubPlan *subplan = (SubPlan *) node; - SubPlanState *sstate; /* * Real execution of a MULTIEXPR SubPlan has already been @@ -1405,19 +1407,7 @@ ExecInitExprRec(Expr *node, ExprState *state, break; } - if (!state->parent) - elog(ERROR, "SubPlan found with no parent plan"); - - sstate = ExecInitSubPlan(subplan, state->parent); - - /* add SubPlanState nodes to state->parent->subPlan */ - state->parent->subPlan = lappend(state->parent->subPlan, - sstate); - - scratch.opcode = EEOP_SUBPLAN; - scratch.d.subplan.sstate = sstate; - - ExprEvalPushStep(state, &scratch); + ExecInitSubPlanExpr(subplan, state, resv, resnull); break; } @@ -2618,29 +2608,12 @@ ExecPushExprSetupSteps(ExprState *state, ExprSetupInfo *info) foreach(lc, info->multiexpr_subplans) { SubPlan *subplan = (SubPlan *) lfirst(lc); - SubPlanState *sstate; Assert(subplan->subLinkType == MULTIEXPR_SUBLINK); - /* This should match what ExecInitExprRec does for other SubPlans: */ - - if (!state->parent) - elog(ERROR, "SubPlan found with no parent plan"); - - sstate = ExecInitSubPlan(subplan, state->parent); - - /* add SubPlanState nodes to state->parent->subPlan */ - state->parent->subPlan = lappend(state->parent->subPlan, - sstate); - - scratch.opcode = EEOP_SUBPLAN; - scratch.d.subplan.sstate = sstate; - /* The result can be ignored, but we better put it somewhere */ - scratch.resvalue = &state->resvalue; - scratch.resnull = &state->resnull; - - ExprEvalPushStep(state, &scratch); + ExecInitSubPlanExpr(subplan, state, + &state->resvalue, &state->resnull); } } @@ -4040,3 +4013,57 @@ ExecBuildParamSetEqual(TupleDesc desc, return state; } + +static void +ExecInitSubPlanExpr(SubPlan *subplan, + ExprState *state, + Datum *resv, bool *resnull) +{ + ExprEvalStep scratch = {0}; + SubPlanState *sstate; + ListCell *pvar; + ListCell *l; + + if (!state->parent) + elog(ERROR, "SubPlan found with no parent plan"); + + /* + * Generate steps to evaluate input arguments for the subplan. + * + * We evaluate the argument expressions into ExprState's resvalue/resnull, + * and then use PARAM_SET to update the parameter. We do that, instead of + * evaluating directly into the param, to avoid depending on the pointer + * value remaining stable / being included in the generated expression. No + * danger of conflicts with other uses of resvalue/resnull as storing and + * using the value always is in subsequent steps. + * + * Any calculation we have to do can be done in the parent econtext, since + * the Param values don't need to have per-query lifetime. + */ + forboth(l, subplan->parParam, pvar, subplan->args) + { + int paramid = lfirst_int(l); + + ExecInitExprRec(lfirst(pvar), state, + &state->resvalue, &state->resnull); + + scratch.opcode = EEOP_PARAM_SET; + scratch.d.param.paramid = paramid; + /* type isn't needed, but an old value could be confusing */ + scratch.d.param.paramtype = InvalidOid; + ExprEvalPushStep(state, &scratch); + } + + sstate = ExecInitSubPlan(subplan, state->parent); + + /* add SubPlanState nodes to state->parent->subPlan */ + state->parent->subPlan = lappend(state->parent->subPlan, + sstate); + + scratch.opcode = EEOP_SUBPLAN; + scratch.resvalue = resv; + scratch.resnull = resnull; + scratch.d.subplan.sstate = sstate; + + ExprEvalPushStep(state, &scratch); +} diff --git a/src/backend/executor/execExprInterp.c b/src/backend/executor/execExprInterp.c index 19351fe34bf..3cab8a5cdae 100644 --- a/src/backend/executor/execExprInterp.c +++ b/src/backend/executor/execExprInterp.c @@ -446,6 +446,7 @@ ExecInterpExpr(ExprState *state, ExprContext *econtext, bool *isnull) &&CASE_EEOP_PARAM_EXEC, &&CASE_EEOP_PARAM_EXTERN, &&CASE_EEOP_PARAM_CALLBACK, + &&CASE_EEOP_PARAM_SET, &&CASE_EEOP_CASE_TESTVAL, &&CASE_EEOP_MAKE_READONLY, &&CASE_EEOP_IOCOERCE, @@ -1081,6 +1082,13 @@ ExecInterpExpr(ExprState *state, ExprContext *econtext, bool *isnull) EEO_NEXT(); } + EEO_CASE(EEOP_PARAM_SET) + { + /* out of line, unlikely to matter performancewise */ + ExecEvalParamSet(state, op, econtext); + EEO_NEXT(); + } + EEO_CASE(EEOP_CASE_TESTVAL) { /* @@ -2477,6 +2485,20 @@ ExecEvalParamExtern(ExprState *state, ExprEvalStep *op, ExprContext *econtext) errmsg("no value found for parameter %d", paramId))); } +/* + * Set value of a param (currently always PARAM_EXEC) from + * state->res{value,null}. + */ +void +ExecEvalParamSet(ExprState *state, ExprEvalStep *op, ExprContext *econtext) +{ + ParamExecData *prm; + + prm = &(econtext->ecxt_param_exec_vals[op->d.param.paramid]); + prm->value = state->resvalue; + prm->isnull = state->resnull; +} + /* * Raise error if a CURRENT OF expression is evaluated. * diff --git a/src/backend/executor/execProcnode.c b/src/backend/executor/execProcnode.c index 4d288bc8d41..f62bb28140f 100644 --- a/src/backend/executor/execProcnode.c +++ b/src/backend/executor/execProcnode.c @@ -393,6 +393,10 @@ ExecInitNode(Plan *node, EState *estate, int eflags) /* * Initialize any initPlans present in this node. The planner put them in * a separate list for us. + * + * The defining characteristic of initplans is that they don't have + * arguments, so we don't need to evaluate them (in contrast to + * ExecInitSubPlanExpr()). */ subps = NIL; foreach(l, node->initPlan) @@ -401,6 +405,7 @@ ExecInitNode(Plan *node, EState *estate, int eflags) SubPlanState *sstate; Assert(IsA(subplan, SubPlan)); + Assert(subplan->args == NIL); sstate = ExecInitSubPlan(subplan, result); subps = lappend(subps, sstate); } diff --git a/src/backend/executor/nodeSubplan.c b/src/backend/executor/nodeSubplan.c index c136f75ac24..3458ac007cd 100644 --- a/src/backend/executor/nodeSubplan.c +++ b/src/backend/executor/nodeSubplan.c @@ -107,7 +107,7 @@ ExecHashSubPlan(SubPlanState *node, TupleTableSlot *slot; /* Shouldn't have any direct correlation Vars */ - if (subplan->parParam != NIL || node->args != NIL) + if (subplan->parParam != NIL || subplan->args != NIL) elog(ERROR, "hashed subplan with direct correlation not supported"); /* @@ -231,7 +231,6 @@ ExecScanSubPlan(SubPlanState *node, TupleTableSlot *slot; Datum result; bool found = false; /* true if got at least one subplan tuple */ - ListCell *pvar; ListCell *l; ArrayBuildStateAny *astate = NULL; @@ -248,26 +247,20 @@ ExecScanSubPlan(SubPlanState *node, oldcontext = MemoryContextSwitchTo(econtext->ecxt_per_query_memory); /* - * Set Params of this plan from parent plan correlation values. (Any - * calculation we have to do is done in the parent econtext, since the - * Param values don't need to have per-query lifetime.) + * We rely on the caller to evaluate plan correlation values, if + * necessary. However we still need to record the fact that the values + * (might have) changed, otherwise the ExecReScan() below won't know that + * nodes need to be rescanned. */ - Assert(list_length(subplan->parParam) == list_length(node->args)); - - forboth(l, subplan->parParam, pvar, node->args) + Assert(list_length(subplan->parParam) == list_length(subplan->args)); + foreach(l, subplan->parParam) { int paramid = lfirst_int(l); - ParamExecData *prm = &(econtext->ecxt_param_exec_vals[paramid]); - prm->value = ExecEvalExprSwitchContext((ExprState *) lfirst(pvar), - econtext, - &(prm->isnull)); planstate->chgParam = bms_add_member(planstate->chgParam, paramid); } - /* - * Now that we've set up its parameters, we can reset the subplan. - */ + /* with that done, we can reset the subplan */ ExecReScan(planstate); /* @@ -817,6 +810,10 @@ slotNoNulls(TupleTableSlot *slot) * as well as regular SubPlans. Note that we don't link the SubPlan into * the parent's subPlan list, because that shouldn't happen for InitPlans. * Instead, ExecInitExpr() does that one part. + * + * We also rely on ExecInitExpr(), more precisely ExecInitSubPlanExpr(), to + * evaluate input parameters, as that allows them to be evaluated as part of + * the expression referencing the SubPlan. * ---------------------------------------------------------------- */ SubPlanState * @@ -844,7 +841,6 @@ ExecInitSubPlan(SubPlan *subplan, PlanState *parent) /* Initialize subexpressions */ sstate->testexpr = ExecInitExpr((Expr *) subplan->testexpr, parent); - sstate->args = ExecInitExprList(subplan->args, parent); /* * initialize my state @@ -1107,7 +1103,7 @@ ExecSetParamPlan(SubPlanState *node, ExprContext *econtext) elog(ERROR, "ANY/ALL subselect unsupported as initplan"); if (subLinkType == CTE_SUBLINK) elog(ERROR, "CTE subplans should not be executed via ExecSetParamPlan"); - if (subplan->parParam || node->args) + if (subplan->parParam || subplan->args) elog(ERROR, "correlated subplans should not be executed via ExecSetParamPlan"); /* diff --git a/src/backend/jit/llvm/llvmjit_expr.c b/src/backend/jit/llvm/llvmjit_expr.c index 1c722c79552..812f8758743 100644 --- a/src/backend/jit/llvm/llvmjit_expr.c +++ b/src/backend/jit/llvm/llvmjit_expr.c @@ -1094,6 +1094,12 @@ llvm_compile_expr(ExprState *state) break; } + case EEOP_PARAM_SET: + build_EvalXFunc(b, mod, "ExecEvalParamSet", + v_state, op, v_econtext); + LLVMBuildBr(b, opblocks[opno + 1]); + break; + case EEOP_SBSREF_SUBSCRIPTS: { int jumpdone = op->d.sbsref_subscript.jumpdone; diff --git a/src/backend/jit/llvm/llvmjit_types.c b/src/backend/jit/llvm/llvmjit_types.c index 876fb640294..0b1df3afe00 100644 --- a/src/backend/jit/llvm/llvmjit_types.c +++ b/src/backend/jit/llvm/llvmjit_types.c @@ -123,6 +123,7 @@ void *referenced_functions[] = ExecEvalNextValueExpr, ExecEvalParamExec, ExecEvalParamExtern, + ExecEvalParamSet, ExecEvalRow, ExecEvalRowNotNull, ExecEvalRowNull, -- 2.37.1.188.g71a8fab31b --2fo66m5ddj2bowyf-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/3] Remove unnecessary volatile qualifiers. @ 2026-02-18 16:31 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-02-18 16:31 UTC (permalink / raw) --- src/backend/replication/syncrep.c | 19 ++++++++----------- src/backend/storage/ipc/procsignal.c | 4 ++-- src/backend/storage/lmgr/lock.c | 2 +- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 5 files changed, 14 insertions(+), 17 deletions(-) diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index 7ea6001e9ad..045fd35786a 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -473,7 +473,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -548,19 +547,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -767,8 +766,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -905,7 +903,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -920,7 +917,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 5d33559926a..97791f979ef 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -283,7 +283,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -394,7 +394,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index e1168ad3837..718de1b5e98 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -309,7 +309,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; /* diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 579e5933d28..a1ec13d66b9 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -36,7 +36,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -256,7 +256,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index 368e4f3f234..14972f7e7cd 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -50,7 +50,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --J5cpktPts8HkLShw Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v1-0002-Remove-SpinLockFree-and-S_LOCK_FREE.patch ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v1 1/1] Remove unnecessary volatile qualifiers. @ 2026-06-30 21:41 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:41 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers to pg_atomic_* variables or local variables that hold a value returned by a pg_atomic_* function. The pointer arguments for the pg_atomic_* functions are volatile-qualified, so there's no need to mark the pointer volatile. Likewise, a local variable that just holds the result of a pg_atomic_* function gains nothing from volatile. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile when they were modified inside a PG_TRY block and used afterward, but the PG_TRY was later removed. --- src/backend/access/transam/clog.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 10 ++++----- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..47975ba892f 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,7 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; + PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..4acef19e563 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) { uint64 local_gen; uint64 shared_gen; - volatile uint32 flags; + uint32 flags; Assert(MyProcSignalSlot); @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --hE8tq9meMVMcgUcn-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* remove unnecessary volatile qualifiers @ 2026-06-30 21:47 Nathan Bossart <nathandbossart@gmail.com> 0 siblings, 1 reply; 653+ messages in thread From: Nathan Bossart @ 2026-06-30 21:47 UTC (permalink / raw) To: pgsql-hackers I looked into some of these earlier [0], but ended up leaving them alone at the time. Here is a new patch that removes all of the volatile markers in the tree that seemed obviously unnecessary to me. [0] https://postgr.es/m/aZX2oUcKf7IzHnnK%40nathan -- nathan ^ permalink raw reply [nested|flat] 653+ messages in thread
* Re: remove unnecessary volatile qualifiers @ 2026-07-06 11:58 Heikki Linnakangas <hlinnaka@iki.fi> parent: Nathan Bossart <nathandbossart@gmail.com> 0 siblings, 1 reply; 653+ messages in thread From: Heikki Linnakangas @ 2026-07-06 11:58 UTC (permalink / raw) To: Nathan Bossart <nathandbossart@gmail.com>; pgsql-hackers On 01/07/2026 00:47, Nathan Bossart wrote: > I looked into some of these earlier [0], but ended up leaving them alone at > the time. Here is a new patch that removes all of the volatile markers in > the tree that seemed obviously unnecessary to me. Thanks! > --- a/src/backend/access/transam/clog.c > +++ b/src/backend/access/transam/clog.c > @@ -450,7 +450,7 @@ static bool > TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, > XLogRecPtr lsn, int64 pageno) > { > - volatile PROC_HDR *procglobal = ProcGlobal; > + PROC_HDR *procglobal = ProcGlobal; > PGPROC *proc = MyProc; > uint32 nextidx; > uint32 wakeidx; You might want to get rid of the local variable altogether and just refer to ProcGlobal directly.. > @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) > { > uint64 local_gen; > uint64 shared_gen; > - volatile uint32 flags; > + uint32 flags; > > Assert(MyProcSignalSlot); > Are you sure about this one? 'flags' is used in the PG_TRY/CATCH block that follows. It is modified in the PG_TRY(), here: > > /* > * To avoid an infinite loop, we must always unset the bit in > * flags. > */ > BARRIER_CLEAR_BIT(flags, type); and read later in the PG_CATCH() block. The rest looks OK to me. - Heikki ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* [PATCH v2 1/1] Remove unnecessary volatile qualifiers. @ 2026-07-06 15:24 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:24 UTC (permalink / raw) This commit cleans up volatile qualifiers that fit the below criteria: * Accesses to shared memory protected by a spinlock or LWLock. Before commit 0709b7ee72, callers had to use volatile when accessing spinlock-protected shared memory. Since spinlock acquire/release became compiler barriers, and because LWLocks provide the same guarantee, that is no longer necessary. These either predate that change or were cargo-culted from code that did. * Pointers used only to find the address of a member. The volatile qualifier only affects accesses made by dereferencing the pointer, so it is unnecessary there. * Accesses to struct members that are marked volatile in the struct definition. There's no need to mark these pointers volatile, either. * Leftovers from removed PG_TRY blocks. These were marked volatile to protect a value that is modified inside a PG_TRY block and used afterward, but the PG_TRY has since been removed. --- src/backend/access/transam/clog.c | 7 +++--- src/backend/catalog/index.c | 2 +- src/backend/commands/async.c | 4 ++-- src/backend/replication/syncrep.c | 19 +++++++--------- src/backend/storage/ipc/procsignal.c | 8 +++---- src/backend/storage/ipc/shm_toc.c | 31 ++++++++++++--------------- src/backend/storage/lmgr/lock.c | 2 +- src/backend/storage/lmgr/proc.c | 3 +-- src/test/modules/test_shm_mq/setup.c | 4 ++-- src/test/modules/test_shm_mq/worker.c | 2 +- 10 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 75012d4b8f0..6f7f6b86eb6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -450,7 +450,6 @@ static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno) { - volatile PROC_HDR *procglobal = ProcGlobal; PGPROC *proc = MyProc; uint32 nextidx; uint32 wakeidx; @@ -493,7 +492,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * different from ours. If another group starts to update a page in the * same bank as ours, they wait until we release the lock. */ - nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst); + nextidx = pg_atomic_read_u32(&ProcGlobal->clogGroupFirst); while (true) { @@ -524,7 +523,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, pg_atomic_write_u32(&proc->clogGroupNext, nextidx); - if (pg_atomic_compare_exchange_u32(&procglobal->clogGroupFirst, + if (pg_atomic_compare_exchange_u32(&ProcGlobal->clogGroupFirst, &nextidx, (uint32) MyProcNumber)) break; @@ -576,7 +575,7 @@ TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, * At this point, any processes trying to do this would create a separate * group. */ - nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst, + nextidx = pg_atomic_exchange_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* Remember head of list so we can perform wakeups after dropping lock. */ diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9407c357f27..81bba4beac7 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3637,7 +3637,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, int save_sec_context; int save_nestlevel; IndexInfo *indexInfo; - volatile bool skipped_constraint = false; + bool skipped_constraint = false; PGRUsage ru0; bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0); bool set_tablespace = false; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index eee8bc29f38..2799f989b96 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -605,7 +605,7 @@ static void CleanupListenersOnExit(void); static bool IsListeningOn(const char *channel); static void asyncQueueUnregister(void); static bool asyncQueueIsFull(void); -static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength); +static bool asyncQueueAdvance(QueuePosition *position, int entryLength); static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe); static ListCell *asyncQueueAddEntries(ListCell *nextNotify); static double asyncQueueUsage(void); @@ -1968,7 +1968,7 @@ asyncQueueIsFull(void) * returns true, else false. */ static bool -asyncQueueAdvance(volatile QueuePosition *position, int entryLength) +asyncQueueAdvance(QueuePosition *position, int entryLength) { int64 pageno = QUEUE_POS_PAGE(*position); int offset = QUEUE_POS_OFFSET(*position); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index e0e30579c59..d870f09e0a0 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -483,7 +483,6 @@ SyncRepInitConfig(void) void SyncRepReleaseWaiters(void) { - volatile WalSndCtlData *walsndctl = WalSndCtl; XLogRecPtr writePtr; XLogRecPtr flushPtr; XLogRecPtr applyPtr; @@ -558,19 +557,19 @@ SyncRepReleaseWaiters(void) * Set the lsn first so that when we wake backends they will release up to * this location. */ - if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] < writePtr) { - walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; + WalSndCtl->lsn[SYNC_REP_WAIT_WRITE] = writePtr; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } - if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr) { - walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); } - if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) + if (WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr) { - walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; + WalSndCtl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr; numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY); } @@ -777,8 +776,7 @@ SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys) n = 0; for (i = 0; i < max_wal_senders; i++) { - volatile WalSnd *walsnd; /* Use volatile pointer to prevent code - * rearrangement */ + WalSnd *walsnd; SyncRepStandbyData *stby; WalSndState state; /* not included in SyncRepStandbyData */ @@ -915,7 +913,6 @@ SyncRepGetStandbyPriority(void) static int SyncRepWakeQueue(bool all, int mode) { - volatile WalSndCtlData *walsndctl = WalSndCtl; int numprocs = 0; dlist_mutable_iter iter; @@ -930,7 +927,7 @@ SyncRepWakeQueue(bool all, int mode) /* * Assume the queue is ordered by LSN */ - if (!all && walsndctl->lsn[mode] < proc->waitLSN) + if (!all && WalSndCtl->lsn[mode] < proc->waitLSN) return numprocs; /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 1397f65f67b..21a77f98c1d 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -295,7 +295,7 @@ CleanupProcSignalState(int status, Datum arg) int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { - volatile ProcSignalSlot *slot; + ProcSignalSlot *slot; if (procNumber != INVALID_PROC_NUMBER) { @@ -380,7 +380,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = 0; i < NumProcSignalSlots; i++) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pg_atomic_fetch_or_u32(&slot->pss_barrierCheckMask, flagbit); } @@ -406,7 +406,7 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) */ for (int i = NumProcSignalSlots - 1; i >= 0; i--) { - volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) @@ -670,7 +670,7 @@ ResetProcSignalBarrierBits(uint32 flags) static bool CheckProcSignal(ProcSignalReason reason) { - volatile ProcSignalSlot *slot = MyProcSignalSlot; + ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 2f9fbb0a519..2217d48c3d9 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -87,7 +87,6 @@ shm_toc_attach(uint64 magic, void *address) void * shm_toc_allocate(shm_toc *toc, Size nbytes) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -103,9 +102,9 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) + allocated_bytes; @@ -117,7 +116,7 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); } - vtoc->toc_allocated_bytes += nbytes; + toc->toc_allocated_bytes += nbytes; SpinLockRelease(&toc->toc_mutex); @@ -130,16 +129,15 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size shm_toc_freespace(shm_toc *toc) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; Size toc_bytes; SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; SpinLockRelease(&toc->toc_mutex); toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry); @@ -170,7 +168,6 @@ shm_toc_freespace(shm_toc *toc) void shm_toc_insert(shm_toc *toc, uint64 key, void *address) { - volatile shm_toc *vtoc = toc; Size total_bytes; Size allocated_bytes; Size nentry; @@ -183,14 +180,14 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) SpinLockAcquire(&toc->toc_mutex); - total_bytes = vtoc->toc_total_bytes; - allocated_bytes = vtoc->toc_allocated_bytes; - nentry = vtoc->toc_nentry; + total_bytes = toc->toc_total_bytes; + allocated_bytes = toc->toc_allocated_bytes; + nentry = toc->toc_nentry; #ifdef USE_ASSERT_CHECKING /* Verify no duplicate keys */ for (Size i = 0; i < nentry; i++) - Assert(vtoc->toc_entry[i].key != key); + Assert(toc->toc_entry[i].key != key); #endif toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry) @@ -208,8 +205,8 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) } Assert(offset < total_bytes); - vtoc->toc_entry[nentry].key = key; - vtoc->toc_entry[nentry].offset = offset; + toc->toc_entry[nentry].key = key; + toc->toc_entry[nentry].offset = offset; /* * By placing a write barrier after filling in the entry and before @@ -218,7 +215,7 @@ shm_toc_insert(shm_toc *toc, uint64 key, void *address) */ pg_write_barrier(); - vtoc->toc_nentry++; + toc->toc_nentry++; SpinLockRelease(&toc->toc_mutex); } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 8d246ed5a4e..5ee80c7632e 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -312,7 +312,7 @@ typedef struct uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]; } FastPathStrongRelationLockData; -static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks; +static FastPathStrongRelationLockData *FastPathStrongRelationLocks; static void LockManagerShmemRequest(void *arg); static void LockManagerShmemInit(void *arg); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 7d01c981a1f..87dd289f626 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -660,8 +660,7 @@ InitAuxiliaryProcess(void) } /* Mark auxiliary proc as in use by me */ - /* use volatile pointer to prevent code rearrangement */ - ((volatile PGPROC *) auxproc)->pid = MyProcPid; + auxproc->pid = MyProcPid; SpinLockRelease(&ProcGlobal->freeProcsLock); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 4f40a61e3d9..991fe27a7fa 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -38,7 +38,7 @@ static worker_state *setup_background_workers(int nworkers, dsm_segment *seg); static void cleanup_background_workers(dsm_segment *seg, Datum arg); static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr); + test_shm_mq_header *hdr); static bool check_worker_status(worker_state *wstate); /* value cached, fetched from shared memory */ @@ -258,7 +258,7 @@ cleanup_background_workers(dsm_segment *seg, Datum arg) static void wait_for_workers_to_become_ready(worker_state *wstate, - volatile test_shm_mq_header *hdr) + test_shm_mq_header *hdr) { bool result = false; diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index e13c05ae5c7..0ba1cfcac47 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -52,7 +52,7 @@ test_shm_mq_main(Datum main_arg) shm_toc *toc; shm_mq_handle *inqh; shm_mq_handle *outqh; - volatile test_shm_mq_header *hdr; + test_shm_mq_header *hdr; int myworkernumber; PGPROC *registrant; -- 2.50.1 (Apple Git-155) --z39t9WErpHrlykOW-- ^ permalink raw reply [nested|flat] 653+ messages in thread
* Re: remove unnecessary volatile qualifiers @ 2026-07-06 15:47 Nathan Bossart <nathandbossart@gmail.com> parent: Heikki Linnakangas <hlinnaka@iki.fi> 0 siblings, 1 reply; 653+ messages in thread From: Nathan Bossart @ 2026-07-06 15:47 UTC (permalink / raw) To: Heikki Linnakangas <hlinnaka@iki.fi>; +Cc: pgsql-hackers On Mon, Jul 06, 2026 at 02:58:12PM +0300, Heikki Linnakangas wrote: > On 01/07/2026 00:47, Nathan Bossart wrote: >> I looked into some of these earlier [0], but ended up leaving them alone at >> the time. Here is a new patch that removes all of the volatile markers in >> the tree that seemed obviously unnecessary to me. > > Thanks! Thanks for reviewing. >> --- a/src/backend/access/transam/clog.c >> +++ b/src/backend/access/transam/clog.c >> @@ -450,7 +450,7 @@ static bool >> TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, >> XLogRecPtr lsn, int64 pageno) >> { >> - volatile PROC_HDR *procglobal = ProcGlobal; >> + PROC_HDR *procglobal = ProcGlobal; >> PGPROC *proc = MyProc; >> uint32 nextidx; >> uint32 wakeidx; > > You might want to get rid of the local variable altogether and just refer to > ProcGlobal directly.. Done. >> @@ -512,7 +512,7 @@ ProcessProcSignalBarrier(void) >> { >> uint64 local_gen; >> uint64 shared_gen; >> - volatile uint32 flags; >> + uint32 flags; >> Assert(MyProcSignalSlot); > > Are you sure about this one? 'flags' is used in the PG_TRY/CATCH block that > follows. It is modified in the PG_TRY(), here: > >> >> /* >> * To avoid an infinite loop, we must always unset the bit in >> * flags. >> */ >> BARRIER_CLEAR_BIT(flags, type); > > and read later in the PG_CATCH() block. Whoops. You are right. I reverted this part. -- nathan ^ permalink raw reply [nested|flat] 653+ messages in thread
* Re: remove unnecessary volatile qualifiers @ 2026-07-07 16:03 Nathan Bossart <nathandbossart@gmail.com> parent: Nathan Bossart <nathandbossart@gmail.com> 0 siblings, 0 replies; 653+ messages in thread From: Nathan Bossart @ 2026-07-07 16:03 UTC (permalink / raw) To: Heikki Linnakangas <hlinnaka@iki.fi>; +Cc: pgsql-hackers Committed. -- nathan ^ permalink raw reply [nested|flat] 653+ messages in thread
end of thread, other threads:[~2026-07-07 16:03 UTC | newest] Thread overview: 653+ messages (download: mbox mbox.gz follow: Atom feed) -- links below jump to the message on this page -- 2022-02-22 02:21 [PATCH 3/4] Reindent and wrap between added sect1 tags Chapman Flack <chap@anastigmatix.net> 2023-02-25 21:39 [PATCH v2] WIP: Evaluate arguments of correlated SubPlans in the referencing ExprState Andres Freund <andres@anarazel.de> 2023-02-25 21:39 [PATCH v1] WIP: Evaluate arguments of correlated SubPlans in the referencing ExprState Andres Freund <andres@anarazel.de> 2026-02-18 16:31 [PATCH v1 1/3] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:41 [PATCH v1 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-06-30 21:47 remove unnecessary volatile qualifiers Nathan Bossart <nathandbossart@gmail.com> 2026-07-06 11:58 ` Re: remove unnecessary volatile qualifiers Heikki Linnakangas <hlinnaka@iki.fi> 2026-07-06 15:47 ` Re: remove unnecessary volatile qualifiers Nathan Bossart <nathandbossart@gmail.com> 2026-07-07 16:03 ` Re: remove unnecessary volatile qualifiers Nathan Bossart <nathandbossart@gmail.com> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org> 2026-07-06 15:24 [PATCH v2 1/1] Remove unnecessary volatile qualifiers. Nathan Bossart <nathan@postgresql.org>
This inbox is served by agora; see mirroring instructions for how to clone and mirror all data and code used for this inbox